package com.bicon.botu.mall.coupon.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.bicon.botu.core.base.common.BusinessException;
import com.bicon.botu.core.base.common.Constants;
import com.bicon.botu.core.base.common.entity.BaseResult;
import com.bicon.botu.core.base.common.utils.BeanMapper;
import com.bicon.botu.core.base.common.utils.JsonUtil;
import com.bicon.botu.mall.coupon.common.CouponStatus;
import com.bicon.botu.mall.coupon.dto.CouponsDto;
import com.bicon.botu.mall.coupon.dto.MyCouponsDto;
import com.bicon.botu.mall.coupon.dto.OrderMyCouponsDto;
import com.bicon.botu.mall.coupon.dto.PathDto;
import com.bicon.botu.mall.coupon.entity.Coupons;
import com.bicon.botu.mall.coupon.entity.MyCoupons;
import com.bicon.botu.mall.coupon.mapper.MyCouponsMapper;
import com.bicon.botu.mall.coupon.service.ICouponsService;
import com.bicon.botu.mall.coupon.service.IMyCouponsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.*;

/**
 * <p>
 * 用户领取的优惠券 服务实现类
 * </p>
 *
 * @author 吕祥
 * @since 2017-07-22
 */
@Slf4j
@Service
public class MyCouponsServiceImpl extends ServiceImpl<MyCouponsMapper, MyCoupons> implements IMyCouponsService {

    @Autowired
    private ICouponsService iCouponsService;

    @Autowired
    private MyCouponsMapper myCouponsMapper;

    /**
     * 新增我的优惠卷
     *
     * @param userId    用户id
     * @param couponsId 优惠券id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult add(String userId, String couponsId) {
        Coupons coupons = new Coupons().selectOne(new EntityWrapper<Coupons>().eq("id", couponsId));
        if (null == coupons) {
            return new BaseResult(CouponStatus.RESPONSE_CODE_602, "优惠劵不存在");
        }
        MyCoupons myCoupons = new MyCoupons();
        List<MyCoupons> myCouponsList = new MyCoupons().selectList(new EntityWrapper<MyCoupons>().eq("user_id", userId).eq("coupons_id", couponsId));
        for (MyCoupons entity : myCouponsList) {
            if (entity.getCouponsId().equals(couponsId)) {
                return new BaseResult(CouponStatus.RESPONSE_CODE_601, "该优惠劵已领取过");
            }
        }
        if (coupons.getGetNumber() < coupons.getNumber()) {
            myCoupons.setUserId(userId);
            myCoupons.setCouponsId(couponsId);
            myCoupons.setCouponsStatus(CouponStatus.MY_COUPONS_UNUSED);
            myCoupons.preInsert();
        } else {
            return new BaseResult(CouponStatus.RESPONSE_CODE_600, "优惠券已领完");
        }
        boolean result = myCoupons.insert();
        if (result) {
            coupons.setGetNumber(coupons.getGetNumber() + 1);
            coupons.updateById();
            return new BaseResult(CouponStatus.RESPONSE_CODE_200, CouponStatus.RESPONSE_MESSAGE_200);
        } else {
            return new BaseResult(CouponStatus.RESPONSE_CODE_500, CouponStatus.RESPONSE_MESSAGE_500);
        }
    }

    /**
     * 删除我的优惠券
     *
     * @param userId     用户id
     * @param couponsIds 优惠券 id Json格式
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult deleteById(String userId, String couponsIds) {
        List<String> idList = JsonUtil.fromJson(couponsIds, ArrayList.class);
        List<MyCoupons> myCouponsList = new ArrayList<MyCoupons>();
        if (null == idList || idList.size() <= 0) {
            return new BaseResult(CouponStatus.RESPONSE_CODE_400, CouponStatus.RESPONSE_MESSAGE_400);
        }
        for (String couponId : idList) {
            MyCoupons myCoupons = new MyCoupons().selectOne(new EntityWrapper<MyCoupons>()
                    .eq("user_id", userId).eq("coupons_id", couponId)
                    .eq("logic_delete", CouponStatus.DEL_LOGIC_NORMAL));
            if (null == myCoupons) {
                return new BaseResult(CouponStatus.RESPONSE_CODE_602, CouponStatus.RESPONSE_MESSAGE_602);
            }
            myCoupons.preDelete();
            myCouponsList.add(myCoupons);
        }
        if (null != myCouponsList && myCouponsList.size() > 0) {
            if (updateBatchById(myCouponsList)) {
                return new BaseResult(CouponStatus.RESPONSE_CODE_200, CouponStatus.RESPONSE_MESSAGE_200);
            }
        }
        return new BaseResult(CouponStatus.RESPONSE_CODE_500, CouponStatus.RESPONSE_MESSAGE_500);
    }


    /**
     * 修改我的优惠券
     *
     * @param id        我的优惠券id
     * @param userId    用户id
     * @param couponsId 优惠券id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult updateById(String id, String userId, String couponsId) {
        MyCoupons myCoupon = new MyCoupons().selectById(id);
        if (null != userId) {
            myCoupon.setUserId(userId);
        }
        if (null != couponsId) {
            myCoupon.setCouponsId(couponsId);
        }
        myCoupon.preUpdate();
        boolean result = myCoupon.updateById();
        if (result) {
            return new BaseResult(CouponStatus.RESPONSE_CODE_200, CouponStatus.RESPONSE_MESSAGE_200);
        } else {
            return new BaseResult(CouponStatus.RESPONSE_CODE_500, CouponStatus.RESPONSE_MESSAGE_500);
        }
    }

    /**
     * 查询用户的优惠券(未使用， 已使用， 已过期三种优惠券信息)
     *
     * @param userId 用户id
     * @return
     */
    @Override
    public Map<String, List<Coupons>> findAllMyCoupons(String userId) {
        //找到用户所有的优惠券
        List<MyCoupons> myCouponsList = new MyCoupons().selectList(new EntityWrapper<MyCoupons>().eq("user_id", userId).eq("logic_delete", CouponStatus.DEL_LOGIC_NORMAL));
        if (myCouponsList.size() <= 0) {
            return null;
        }
        //保存未使用的优惠券
        List<Coupons> couponsUnusedList = new ArrayList<Coupons>();
        //保存用户已过期的优惠券
        List<Coupons> couponsPastDueList = new ArrayList<Coupons>();
        //保存用户已使用的优惠券
        List<Coupons> couopnsHaveBeenUsedList = new ArrayList<Coupons>();
        for (MyCoupons entity : myCouponsList) {
            Coupons coupons = new Coupons().selectById(entity.getCouponsId());
            //判断用户优惠券已使用状态
            if (entity.getCouponsStatus().equals(CouponStatus.MY_COUPONS_HAVE_BEEN_USED)) {
                couopnsHaveBeenUsedList.add(coupons);
                continue;
            }
            try {
                Date dateL = coupons.getLastDate();
                Date dateN = new Date();
                if (dateN.getTime() >= dateL.getTime()) {
                    //设置为已过期
                    entity.setCouponsStatus(CouponStatus.MY_COUPONS_PAST_DUE);
                    entity.updateById();
                    couponsPastDueList.add(coupons);
                    continue;
                } else {
                    //设置为未使用
                    entity.setCouponsStatus(CouponStatus.MY_COUPONS_UNUSED);
                    entity.updateById();
                    couponsUnusedList.add(coupons);
                    continue;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //返回用户 未使用、过期、已使用的优惠券
        Map<String, List<Coupons>> map = new HashMap<String, List<Coupons>>();
        //未使用的
        map.put(CouponStatus.MAP_KEY_UNUSED, couponsUnusedList);
        //过期的
        map.put(CouponStatus.MAP_KEY_PASTDUE, couponsPastDueList);
        //已使用的
        map.put(CouponStatus.MAP_KEY_HAVE_BEEN_USED, couopnsHaveBeenUsedList);
        if (null != map) {
            return map;
        } else {
            return null;
        }
    }

    /**
     * .根据商品查询该商品可用优惠券
     *
     * @param userId       用户id
     * @param classifyPath 分类path
     * @param brandId      品牌id
     * @param productId    商品id
     * @return
     */
    @Override
    public Map<String, List<Coupons>> findCoupon(String userId, String classifyPath, String brandId, String productId) {
        List<MyCoupons> myCouponsList = new MyCoupons().selectList(new EntityWrapper<MyCoupons>().eq("user_id", userId));
        //所有用户领取的优惠劵id
        List<String> couponsIds = new ArrayList<>();
        //用户未使用的优惠劵id
        List<String> couponsIdList = new ArrayList<>();
        myCouponsList.stream().forEach(myCoupons -> {
            couponsIds.add(myCoupons.getCouponsId());
            if (CouponStatus.MY_COUPONS_UNUSED.equals(myCoupons.getCouponsStatus())) {
                couponsIdList.add(myCoupons.getCouponsId());
            }
        });
        //找到用户领取的所有优惠劵
        List<Coupons> coupons = new ArrayList<>();
        if (!CollectionUtils.isEmpty(couponsIds)) {
            coupons = new Coupons().selectList(new EntityWrapper<Coupons>().in("id", couponsIds));
        }
        //找到用户未使用的优惠并且对商品可用的
        List<Coupons> couponsList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(couponsIdList)) {
            couponsList = new Coupons().selectList(new EntityWrapper<Coupons>().in("id", couponsIdList));
            couponsList = this.verify(couponsList, classifyPath, brandId, productId);
        }
        //获取商城所有在发行期内的优惠劵
        List<Coupons> mallCouponsList = iCouponsService.findAllRedis();
        if (!CollectionUtils.isEmpty(mallCouponsList) && !CollectionUtils.isEmpty(coupons)) {
            mallCouponsList.removeAll(coupons);
        }
        if (!CollectionUtils.isEmpty(mallCouponsList)) {
            mallCouponsList = this.verify(mallCouponsList, classifyPath, brandId, productId);
        }
        Map<String, List<Coupons>> resultMap = new HashMap<String, List<Coupons>>();
        resultMap.put("Unclaimed", mallCouponsList);
        resultMap.put("myCoupons", couponsList);
        return resultMap;
    }

    /**
     * 根据多个商品查询这些商品可用的用户已领取的优惠券
     *
     * @param userId 用户id
     * @param paths  Json格式的path集合
     * @return
     */
    @Override
    public Map<String, List<Coupons>> multiFindCoupons(String userId, String paths) {
        Map<String, List<Coupons>> map = this.findAllMyCoupons(userId);
        if (null != map) {
            //获取个人未使用的优惠券
            List<Coupons> myCouponsList = map.get(CouponStatus.MAP_KEY_UNUSED);
            List<PathDto> pathDtoList = JSONObject.parseArray(paths, PathDto.class);
            Map<String, List<Coupons>> couponsMap = new HashMap<String, List<Coupons>>();
            for (PathDto entity : pathDtoList) {
                List<Coupons> couponsList = this.verify(myCouponsList, entity.getClassifyPaths(), entity.getBrandIds(), entity.getProductIds());
                couponsMap.put(entity.getProductIds(), couponsList);
            }
            return couponsMap;
        } else {
            return map;
        }
    }

    /**
     * 根据多个商品查询这些商品可用的用户已领取的优惠券 (安卓)
     *
     * @param userId 用户id
     * @param paths  Json格式的path集合
     * @return
     */
    @Override
    public List<CouponsDto> findMyCouponsByMultiProduct(String userId, String paths) {
        Map<String, List<Coupons>> map = this.findAllMyCoupons(userId);
        List<CouponsDto> couponsDtoList = new ArrayList<CouponsDto>();
        if (null != map) {
            List<Coupons> myCouponsList = map.get(CouponStatus.MAP_KEY_UNUSED);
            List<PathDto> pathDtoList = JSONObject.parseArray(paths, PathDto.class);
            for (PathDto pathDto : pathDtoList) {
                List<Coupons> list = this.verify(myCouponsList, pathDto.getClassifyPaths(), pathDto.getBrandIds(), pathDto.getProductIds());
                if (!CollectionUtils.isEmpty(list)) {
                    for (Coupons coupons : list) {
                        CouponsDto dto = new CouponsDto();
                        BeanMapper.copy(coupons, dto);
                        dto.setProductId(pathDto.getProductIds());
                        couponsDtoList.add(dto);
                    }
                }
            }
        }
        return couponsDtoList;
    }

    /**
     * 根据优惠券状态 查询我的优惠券列表
     * @param status 优惠券状态
     * @param userId 用户ID
     * @return
     */
    @Override
    public List<MyCouponsDto> getMyCouponsListByStatus(String status,String userId) {
        return myCouponsMapper.getMyCouponsListByStatus(status,userId) ;
    }


    /**
     * 校验优惠券
     *
     * @param couponsList  优惠券集合
     * @param classifyPath 分类path
     * @param brandId      品牌id
     * @param productId    商品id
     * @return
     */
    private List<Coupons> verify(List<Coupons> couponsList, String classifyPath, String brandId, String productId) {
        List<Coupons> resultList = new ArrayList<Coupons>();
        couponsList.stream().forEach(entity -> {
            if (null != classifyPath) {
                if (classifyPath.contains(entity.getPath())) {
                    resultList.add(entity);
                }
            }
            if (null != brandId) {
                if (entity.getPath().equals(brandId)) {
                    resultList.add(entity);
                }
            }
            if (null != productId) {
                if (entity.getPath().contains(productId)) {
                    resultList.add(entity);
                }
            }
        });
        if (resultList.size() > 0) {
            return resultList;
        } else {
            return null;
        }
    }

    /**
     * 查询我的优惠券
     *
     * @param myCoupons 多个优惠券id
     * @return
     */
    @Override
    public List<String> selectMyCoupons(List<String> myCoupons) {
        if (CollectionUtils.isEmpty(myCoupons)) {
            throw new BusinessException("优惠券不存在");
        }
        List<MyCoupons> couponsList = this.selectList(new EntityWrapper<MyCoupons>()
                .eq("logic_delete", Constants.DEL_LOGIC_NORMAL).in("id", myCoupons));
        if (CollectionUtils.isNotEmpty(couponsList)) {
            String[] result = couponsList.stream().map(MyCoupons::getCouponsId).toArray(String[]::new);

            List<Coupons> list = iCouponsService.selectList(new EntityWrapper<Coupons>().in("id", result));
            if (CollectionUtils.isNotEmpty(list)){
                String[] name = list.stream().map(Coupons :: getName).toArray(String[]::new);
                return Arrays.asList(name);
            }
        }
        return null;
    }

}
